package com.github.lzm320a99981e.autocoding.domain.condition;

import com.google.common.base.Joiner;
import lombok.NonNull;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Objects;
import java.util.UUID;

/**
 * 条件接口
 */
public interface Conditionable {
    String PLACEHOLDER = UUID.randomUUID().toString().replace("-", "");

    /**
     * 条件连接
     */
    enum Join {
        AND, OR
    }

    /**
     * 条件操作符
     */
    enum Operator {
        EQ("= " + PLACEHOLDER),
        NE("!= " + PLACEHOLDER),
        GT("> " + PLACEHOLDER),
        GE(">= " + PLACEHOLDER),
        LT("< " + PLACEHOLDER),
        LE("<= " + PLACEHOLDER),
        IN("IN (" + PLACEHOLDER + ")"),
        NI("NOT IN (" + PLACEHOLDER + ")"),
        LIKE("LIKE '%" + PLACEHOLDER + "%'"),
        NLIKE("NOT LIKE '%" + PLACEHOLDER + "%'"),
        LLIKE("LIKE '%" + PLACEHOLDER + "'"),
        RLIKE("LIKE '" + PLACEHOLDER + "%'"),
        BETWEEN("BETWEEN " + (PLACEHOLDER + "MIN") + " AND " + PLACEHOLDER + "MAX") {
            @SuppressWarnings("rawtypes")
			@Override
            public String parseExpression(Object value) {
                Object min = null;
                Object max = null;
                if (Iterable.class.isAssignableFrom(value.getClass())) {
                    Iterator iterator = ((Iterable) value).iterator();
                    min = iterator.next();
                    max = iterator.next();

                }
                if (value.getClass().isArray()) {
                    min = Array.get(value, 0);
                    max = Array.get(value, 1);

                }
                if (Objects.isNull(min)) {
                    throw new RuntimeException("不支持的值类型：" + value.getClass());
                }

                if (Number.class.isAssignableFrom(min.getClass())) {
                    return getExpression().replace(PLACEHOLDER + "MIN", min.toString()).replace(PLACEHOLDER + "MAX", max.toString());
                }

                return getExpression().replace(PLACEHOLDER + "MIN", "'" + min + "'").replace(PLACEHOLDER + "MAX", "'" + max + "'");
            }
        };

        @SuppressWarnings("rawtypes")
		public String parseExpression(@NonNull Object value) {
            if (Arrays.asList(EQ, NE, GT, GE, LT, LE).contains(this)) {
                if (Number.class.isAssignableFrom(value.getClass())) {
                    return getExpression().replace(PLACEHOLDER, value.toString());
                }
                return getExpression().replace(PLACEHOLDER, "'" + value.toString() + "'");
            }

            if (Arrays.asList(IN, NI).contains(this)) {
                if (Iterable.class.isAssignableFrom(value.getClass())) {
                    return getExpression().replace(PLACEHOLDER, "'" + Joiner.on("','").join((Iterable) value) + "'");
                }
                if (value.getClass().isArray()) {
                    return getExpression().replace(PLACEHOLDER, "'" + Joiner.on("','").join(Arrays.asList(value)) + "'");
                }
                return getExpression().replace(PLACEHOLDER, "'" + value.toString() + "'");
            }

            if (Arrays.asList(LIKE, NLIKE, LLIKE, RLIKE).contains(this)) {
                return getExpression().replace(PLACEHOLDER, value.toString());
            }

            throw new RuntimeException("不支持的计算符：" + this);
        }


        private final String expression;
        @SuppressWarnings("unused")
		private boolean none = false;

        Operator(String expression) {
            this.expression = expression;
        }

        public String getExpression() {
            return expression;
        }

        public Operator none() {
            return this;
        }
    }

    /**
     * 条件字段
     *
     * @return
     */
    String getProperty();

    /**
     * 条件值
     *
     * @return
     */
    Object getValue();

    /**
     * 条件连接符
     *
     * @return
     */
    Join getJoin();

    /**
     * 条件操作符
     *
     * @return
     */
    Operator getOperator();
}
